package com.zk.controller;

import com.alibaba.excel.EasyExcel;
import com.zk.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Controller
@RequestMapping("user")
public class UserController {
    @RequestMapping("save")
    @ResponseBody
    public String save(){
        System.out.println("user save...");
        return "{'module':'user save'}";
    }

    @RequestMapping("delete")
    @ResponseBody
    public String delete(){
        System.out.println("user delete ...");
         return "{'module':'user delete'}";
    }

    @RequestMapping("commonParam")
    @ResponseBody
    public String commonParam(String name,int age){
        System.out.println("普通参数传递 name ==> "+name);
        System.out.println("普通参数传递 age ==> "+age);
        return "{'module':'commonParam'}";
    }
//    如果形参与地址参数名不一致该如何解决? url中是name，方法中形参是userName.解决方案:使用@RequestParam注解
//    写上@RequestParam注解框架就不需要自己去解析注入，能提升框架处理性能
    @RequestMapping("commonParamDifferentName")
    @ResponseBody
    public String commonParamDifferentName(@RequestParam("name") String userName, int age){
        System.out.println("普通参数传递 name ==> "+userName);
        System.out.println("普通参数传递 age ==> "+age);
        return "{'module':'commonParam'}";
    }

    //POJO参数：请求参数与形参对象中的属性对应即可完成参数传递
//    POJO参数接收，前端GET和POST发送请求数据的方式不变。
//    请求参数key的名称要和POJO中属性的名称一致，否则无法封装。
//    嵌套POJO参数：请求参数名与形参对象属性名相同，按照对象层次结构关系即可接收嵌套POJO属性参数.address.city
    @RequestMapping("pojoParam")
    @ResponseBody
    public String pojoParam(User user){
        System.out.println("pojo参数传递 user ==> "+user);
        return "{'module':'pojo param'}";
    }

    //数组参数：同名请求参数可以直接映射到对应名称的形参数组对象中
    @RequestMapping("arrayParam")
    @ResponseBody
    public String arrayParam(String[] likes){
        System.out.println("数组参数传递 likes ==> "+ Arrays.toString(likes));
        return "{'module':'array param'}";
    }
//    错误的原因是:SpringMVC将List看做是一个POJO对象来处理，将其创建一个对象并准备把前端的数
//    据封装到对象中，但是List是一个接口无法创建对象，所以报错
//集合参数：同名请求参数可以使用@RequestParam注解映射到对应名称的集合对象中作为数据
    @RequestMapping("listParam")
    @ResponseBody
    public String listParam(@RequestParam List<String> likes){
        System.out.println("集合参数传递 likes ==> "+ likes);
        return "{'module':'list param'}";
    }

    //使用@RequestBody注解将外部传递的json数组数据映射到形参的集合对象中作为数据
    @RequestMapping("listParamForJson")
    @ResponseBody
    public String listParamForJson(@RequestBody List<String> likes){
        System.out.println("list common(json)参数传递 list ==> "+likes);
        return "{'module':'list common for json param'}";
    }


    //使用@RequestBody注解将外部传递的JSON对象数据映射到形参的对象中作为数据
    @RequestMapping("pojoParamForJson")
    @ResponseBody
    public String pojoParamForJson(@RequestBody User user){
        System.out.println("pojo(json)参数传递 user ==> "+user);
        return "{'module':'pojo for json param'}";
    }

    //使用@RequestBody注解将外部传递的JSON对象数组数据映射到形参的集合对象中作为数据
    @RequestMapping("listPojoParamForJson")
    @ResponseBody
    public String listPojoParamForJson(@RequestBody List<User> list){
        System.out.println("list pojo(json)参数传递 list ==> "+list);
        return "{'module':'list pojo for json param'}";
    }
//    @RequestBody与@RequestParam区别
//    @RequestParam用于接收url地址传参，表单传参【application/x-www-formurlencoded】
//    @RequestBody用于接收json数据【application/json】


    // 跳转页面
    //1.此处不能添加@ResponseBody,如果加了该注入，会直接将page.jsp当字符串返回前端
    //2.方法需要返回String
    @RequestMapping("toJumpPage")
    public String toJumpPage(){
        System.out.println("跳转页面");
        return "page.jsp";
    }

    // 返回文本
    @RequestMapping("toText")
    //注意此处该注解就不能省略，如果省略了,会把response text当前页面名称去查找，如果没有会报404错误
    @ResponseBody
    public String toText(){
        System.out.println("返回纯文本数据");
        return "response text";
    }

    // 响应POJO对象.返回值为实体类对象，设置返回值为实体类类型，即可实现返回对应对象的json数据，需要依赖
    //@ResponseBody注解和@EnableWebMvc注解
    @RequestMapping("toJsonPOJO")
    @ResponseBody
    public User toJsonPOJO(){
        System.out.println("返回json对象数据");
        User user = new User();
        user.setName("itcast");
        user.setAge(15);
        return user;
    }


    @RequestMapping("/toJsonList")
    @ResponseBody
    public List<User> toJsonList(){
        System.out.println("返回json集合数据");
        User user1 = new User();
        user1.setName("传智播客");
        user1.setAge(15);
        User user2 = new User();
        user2.setName("黑马程序员");
        user2.setAge(12);

        List<User> userList = new ArrayList<User>();
        userList.add(user1);
        userList.add(user2);
        return userList;
    }

//    @ResponseBody用法
//    该注解可以写在类上或者方法上
//    写在类上就是该类下的所有方法都有@ReponseBody功能
//    当方法上有@ReponseBody注解后
//    方法的返回值为字符串，会将其作为文本内容直接响应给前端
//    方法的返回值为对象，会将对象转换成JSON响应给前端

    @GetMapping("/testRespExcel")
    public void testRespExcel(HttpServletResponse response){
        response.addHeader("Content-Disposition", "attachment;filename=" + "huyuqiao.xlsx");
        response.setContentType("application/vnd.ms-excel;charset=gb2312");
        try {
//            从HttpServletResponse中获取OutputStream输出流
            ServletOutputStream outputStream = response.getOutputStream();
            /*
             * EasyExcel 有多个不同的read方法，适用于多种需求
             * 这里调用EasyExcel中通过OutputStream流方式输出Excel的write方法
             * 它会返回一个ExcelWriterBuilder类型的返回值
             * ExcelWriterBuilde中有一个doWrite方法，会输出数据到设置的Sheet中
             */
            EasyExcel.write(outputStream, User.class).sheet("测试数据").doWrite(getAllUser());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public List<User> getAllUser(){
        List<User> userList = new ArrayList<>();
        for (int i=0;i<100;i++){
            User user = User.builder().name("测试数据"+ i).password("ceshi").age(i).build();
            userList.add(user);
        }
        return userList;
    }


}
